package com.qlogic.commons.utils.os;

import java.util.HashMap;
import java.util.Map;

import com.qlogic.commons.exceptions.BaseException;
import com.qlogic.commons.utils.strings.StringUtils;

public class OsCommandExecuter {
	
	private static String osName = System.getProperty("os.name");
	
	private boolean singleShell;
	private Map results = new HashMap ();
	private OsCommandResult singleShellResult; 
	
	public OsCommandExecuter (boolean singleShell) {
		this.singleShell = singleShell;
	}
	
	public OsCommandExecuter () {
	}
	
	public OsCommandResult execute (String command) {
		return execute (command, true);
	}
	
	public OsCommandResult execute (String command, boolean shortMsg) {
		Runtime rt = Runtime.getRuntime();
		Process proc = null;
		try {
			proc = rt.exec (getOsShell () + command);
		} catch (Throwable t) {
			singleShellResult = new OsCommandResult (shortMsg ? t.getMessage () : new BaseException (t).getCauseText ());
		}
		OsCommandExecuterThread errorThread = 
			new OsCommandExecuterThread (this, command, OsCommandResult.ERROR, proc.getErrorStream());
		OsCommandExecuterThread infoThread = 
			new OsCommandExecuterThread (this, command, OsCommandResult.INFO, proc.getInputStream ());
		errorThread.start ();
		infoThread.start ();
		try {
			proc.waitFor();
		} catch (Throwable t) {
			// IGNORE
		}
		return singleShellResult;
	}
	
	public void execute (String [] commands) {
		Runtime rt = Runtime.getRuntime();
		String [] shells = new String [commands.length + 1];
		if (singleShell) {
			shells [0] = getOsShell ();
			for (int i = 0; i < commands.length; i++) {
				shells [i + 1] = commands [i];
			}
			try {
				Process proc = rt.exec (shells);
				String shellsCommand = StringUtils.arrayToString (shells, StringUtils.LINE_SEP);
				OsCommandExecuterThread errorThread = 
					new OsCommandExecuterThread (this, shellsCommand, OsCommandResult.ERROR, proc.getErrorStream());
				OsCommandExecuterThread infoThread = 
					new OsCommandExecuterThread (this, shellsCommand, OsCommandResult.INFO, proc.getInputStream ());
				errorThread.start();
				infoThread.start();
				proc.waitFor();
			} catch (Throwable t) {
				singleShellResult = new OsCommandResult (new BaseException (t).getCauseText ());
			}
		} else {
			for (int i = 0; i < commands.length; i++) {
				execute (getOsShell () + commands [i]);
			}
			
		}
	}
	
	public OsCommandResult getResult (String command) {
		if (singleShell) {
			return singleShellResult;
		} else {
			return (OsCommandResult)results.get (command);
		}
	}
	
	void addResult (String command, OsCommandResult osCommandResult) {
		results.put (command, osCommandResult);
	}
	
	private String getOsShell () {
		String osShell = "";
		if (osName.toUpperCase().indexOf ("UNIX") >= 0 || osName.toUpperCase().indexOf ("LINUX") >= 0) {
			osShell = "sh -c ";
		} else if (osName.equals("Windows 95")) {
			osShell = "command /C ";
		} else {
			osShell = "cmd /C ";
		}
		return osShell;
	}

	public boolean isSingleShell() {
		return singleShell;
	}

	void setSingleShellResult(OsCommandResult singleShellResult) {
		this.singleShellResult = singleShellResult;
	}
	
}
